/*

  Loads all stocks stored in in table "ALL_STOCKS".
  Can add a new stock into this table.

*/

#include "stock.h"
//#include "global/global.h"

Stock::Stock(int flag,QObject *parent) :
    Instruments(parent)
{
    this->flag=flag;
    init();
}

Stock::Stock(const Stock &stock)
{
    //this->stocks=stock.getStocks();
    this->staticStockNames=stock.getStockNames();
    this->stockSymbols=stock.getStockSymbols();
    setValSymbols(stock.getValSymbols());
    initModel(QString(VALUE_NAMES).split(","));  //init model for view
}

Stock::Stock(const QString& dbName,int flag, QObject *parent):Instruments(dbName,parent)
{
    this->flag=flag;
    init();
}

Stock::Stock(Config *cfg,int flag, QObject *parent):
    Instruments(parent)
{
    this->flag=flag;
    init();
}

Stock::Stock(Config* cfg,const QString& dbName,int flag, QObject *parent):Instruments(cfg,dbName,parent)
{
    this->flag=flag;
    init();
}

Stock::~Stock()
{

}

//TODO!
/*converts stockName to a valid String for the db*/
QString Stock::convertStockName(const QString &stockName)
{
    //QString ret(stockName);
    /*
     * ->_
     */
    //ret.replace()
}

/*adds a new stock into db*/
void Stock::addStock(const QString &stockName, const QString &stockSymbol)
{
    QStringList fieldList,valList;

    fieldList<<STOCK_NAME_FIELD<<STOCK_SYMBOL_FIELD;
    valList<<stockName<<stockSymbol;

    /*create the stock table, if it does not exist*/
    addTable(STOCK_TABLE,fieldList);

    /*add a new stock table*/
    addTable(stockName,valSymbols);          //add new table
    /*add to current lists*/
    stockNames.append(stockName);
    stockSymbols.append(stockSymbol);
    QMap<QString,QList<QStandardItem*> >::iterator iter;
    iter=stocks.insert(stockSymbol,QList<QStandardItem*>());

    /*fill the list with items*/
    while(iter.value().count()<valSymbols.count())
        iter.value().append(new QStandardItem());

    /*add values*/
    if(!containsValue(STOCK_TABLE,STOCK_SYMBOL_FIELD,stockSymbol))   //check, if value already available
        addValues(STOCK_TABLE,fieldList,valList);                   //insert value

    qDebug()<<"Emitting Signal";

    emit newValueSignal(stockName,iter.value());

    /*reconnect*/ //TODO: put it in a own function
    QString url="/streamer/1.0?s="+stockSymbols.join(",")+"&k="+VALUE_SYMBOLS+"&j="+VALUE_SYMBOLS+"&r=0&callback=parent.yfs_u1f&mktmcb=parent.yfs_mktmcb&gencallback=parent.yfs_gencb&region=DE&lang=de-DE&localize=0&mu=1";
    ConnectionHandler::instance()->setUrl("streamerapi.finance.yahoo.com",url);
}

/*adds multiple stocks*/
void Stock::addStock(const QStringList &stockNames, const QStringList &stockSymbols)
{
    QStringList fieldList;

    /*create the stock table, if it does not exist*/
    fieldList<<STOCK_NAME_FIELD<<STOCK_SYMBOL_FIELD;    //create field list
    addTable(STOCK_TABLE,fieldList);                    //add table

    /*add values*/
    if(!containsValue(STOCK_TABLE,STOCK_SYMBOL_FIELD,stockSymbols))   //check, if value already available
    {
        qDebug()<<"Adding values";
        if(stockNames.count()==stockSymbols.count())                 //if bijectiv
        {
            QList<QStringList> list;
            list<<stockNames<<stockSymbols;
            addValues(STOCK_TABLE,fieldList,list);                   //insert stock names

            /*add a new stock table*/
            for(int i=0;i<stockNames.count();i++)
            {
                addTable(stockNames.at(i),valSymbols);          //add new table
                stocks.insert(stockSymbols.at(i),QList<QStandardItem*>());
            }
            /*add to current lists*/
            this->stockNames.append(stockNames);
            this->stockSymbols.append(stockSymbols);
        }

    }

}

QMap<QString,QList<QStandardItem*> >::iterator Stock::addStock(const QString &stock,int flag, const QMap<QString, QList<QStandardItem *> > &initVals)
{
    QMap<QString,QList<QStandardItem*> >::iterator iter=0;

    if(flag==NO_FLAG)
    {
        if(!stocks.contains(stock))
        {
            qDebug()<<"Stock::addStock(): "<<"Stock "<<stock<<" in map inserted.";

            iter=stocks.insert(stock,QList<QStandardItem*>());

            /*fill the list with items*/
            int i=0;
            while(iter.value().count()<valSymbols.count())
            {
                if(initVals.contains(stock))
                    iter.value().append(initVals.value(stock).at(i++)->clone());
                else
                    iter.value().append(new QStandardItem());
            }
        }
    }

    if(flag==ADD_STOCK_NAME)
    {
        int index=-1;
        if((index=staticStockNames.indexOf(stock))>-1)  //stock name is available
        {
            if(!stockNames.contains(staticStockNames.at(index)))
                stockNames.append(staticStockNames.at(index));

            qDebug()<<"Stock::addStock(): "<<"All stocks: "<<stocks;
            if(!stocks.contains(stockSymbols.at(index)))
            {
                qDebug()<<"Stock::addStock(): "<<"Adding stock "<<staticStockNames.at(index);
                iter=addStock(stockSymbols.at(index),NO_FLAG,initVals);   //add to stock map

                emit newValueSignal(staticStockNames.at(index),iter.value());
            }
        }
    }

    return iter;
}

void Stock::setStockNames(const QStringList &names)
{
    stockNames=names;
}

QStringList Stock::getStockNames()const
{
    return stockNames;
}

void Stock::setStockSymbols(const QStringList &symbols)
{
    stockSymbols=symbols;
}

QStringList Stock::getStockSymbols()const
{
    return stockSymbols;
}

void Stock::setValSymbols(const QStringList &valsymbols)
{
    valSymbols=valsymbols;
}

QStringList Stock::getValSymbols()const
{
    return valSymbols;
}

/*sets the current value of a stock in stocks and save it to the db*/
void Stock::setValue(const QString &stockSymbol, QMap<QString, qreal> &vals)
{
    if(!stocks.contains(stockSymbol))
        return;

    QList<QStandardItem*> tmpList=stocks[stockSymbol];
    QList<QStandardItem*>::iterator iter;
    int stockIndex=stockSymbols.indexOf(stockSymbol);   //get the stock index

    /*fill the list with empty values*/
    while(tmpList.count()<valSymbols.count())
        tmpList.append(new QStandardItem());

#ifdef SET_CURRENT_TIME
    /*set the current system date/time, if no time stamp was sent*/
    if(!vals.keys().contains("t10") || vals.value("t10")==0)
        vals.insert("t10",QDateTime::currentDateTime().toTime_t());
#endif

    /*save new values*/
    for(int i=0;i<valSymbols.count();i++)  //go through the string list
    {
        /*create a temp item and fill it, if the valueSymbol exists*/
        QStandardItem *tmpItem=tmpList[i];

        /*if the current valSymbol is in the map -> save the value*/
        if(vals.keys().contains(valSymbols.at(i)))
        {
            /*calc the state for the value changed signal*/
            qreal val=vals.value(valSymbols.at(i));
            qreal oldVal=tmpItem->text().toFloat();
            int c=1;
            if(val>oldVal)
                c=0;
            if(val<oldVal)
                c=2;

            tmpItem->setText(QString("%1").arg(val));
            valueChangedSignal(tmpItem,c);    //emit signal
        }
    }

    /*if the stock symbol exist, add values to db*/
    if(stockIndex>=0 && flag!=LOAD_NO_STOCKS)              //check, if symbol exists
    {
        /*check, if works with vals.keys() because of the type*/
        addValues(stockNames.at(stockIndex),vals.keys(),vals.values());  //add values to table
        qDebug()<<"Stock::setValue(): "<<"Adding value: "<<stockNames.at(stockIndex)<<" : "<<vals.keys()<<" : "<<vals.values();
    }
}

/*return the item of the given position*/
QStandardItem* Stock::getItem(int row, int col)
{
    QString symbol=stockSymbols.at(row);
    return getItem(symbol,col);
}

QStandardItem *Stock::getItem(const QString &stockSymbol, int col)
{
   // qDebug()<<"stockSymbols.count(): "<<stockSymbols.count()<<" : "<<row<<" : "<<stocks.keys().count();
    if(!stockSymbols.contains(stockSymbol))
        return new QStandardItem();

    if(col<0)
        return new QStandardItem();

    /*fill list with empty values*/
   // qDebug()<<"Fill list from "<<stocks[symbol].count()<<" to "<<col;
    while(stocks[stockSymbol].count()<=col)
        stocks[stockSymbol].append(new QStandardItem());

    qDebug()<<"Returning: "<<stockSymbol<<" | "<<stocks[stockSymbol][col];
    return stocks[stockSymbol][col];   //return address of item
}

/*returns the value "valSymbol" of the given stockSymbol*/
QStandardItem* Stock::getValue(const QString &stockSymbol, const QString &valSymbol)
{
    int index=valSymbols.indexOf(valSymbol);                 //get the index of the given valSymbol

    qDebug()<<"Stock::getValue(): "<<"Stock symbol: "<<stockSymbol<<"Value symbol index: "<<index;

    return getItem(stockSymbol,index);
}

/*return all stored stockNames*/
QStringList Stock::getAllStocks()const
{
    return stocks.keys();
}

/*get all current stocks*/
QMap<QString,QList<QStandardItem*> > Stock::getStocks()const
{
    return stocks;
}

/*set the current stocks with values*/
void Stock::setStocks(const QMap<QString,QList<QStandardItem*> > &s)
{
    stocks=s;
}

QList<QStandardItem *> Stock::getStockValues(const QString &stockSymbol) const
{
    if(stocks.contains(stockSymbol))
        return stocks.value(stockSymbol);
    return QList<QStandardItem*>();
}

//TODO! : save stockname and stocksymbol in a map!!!
QString Stock::getStockSymbolByName(const QString &stockName)
{
    /*int index=stockNames.indexOf(stockName);
    if(index<0)
        return QString();*/
    QStringList valFields;
    valFields<<STOCK_SYMBOL_FIELD;
    return getRow(STOCK_TABLE,valFields,QString(STOCK_NAME_FIELD)+"='"+stockName+"'").value(STOCK_SYMBOL_FIELD).toString();
}

Stock& Stock::operator=(const Stock& s)
{
    setStaticStockNames(s.getStockNames());
    setStocks(s.getStocks());
    return *this;
}

/*load all stock information from db*/
void Stock::init()
{
    qDebug()<<"INIT_FLAG: "<<flag;
    //this->cfg=cfg;                      //copy pointer, don't delete

    /*load stock names and symbols*/
    qDebug()<<"Lese StockNames";
    if(flag!=LOAD_NO_STOCKS)
        getColumn(&stockNames,STOCK_NAME_FIELD,STOCK_TABLE,true);   //load stock names
    else
        getColumn(&staticStockNames,STOCK_NAME_FIELD,STOCK_TABLE,true); //TODO: load static stock names in the global stock-object!

    getColumn(&stockSymbols,STOCK_SYMBOL_FIELD,STOCK_TABLE,true);   //TODO: load in global instance


    qDebug()<<"Lese KEYS";
    setValSymbols(QString(VALUE_SYMBOLS).split(","));

    if(flag!=LOAD_NO_STOCKS)
    {
        qDebug()<<"Fuelle map...";
        /*fill the map with the stockSymbols*/
        for(int i=0;i<stockSymbols.count();i++)
        {
            /*add a new stock table, if a new stockName was found*/
            addTable(stockNames.at(i),valSymbols);
            stocks.insert(QString(stockSymbols.at(i)),QList<QStandardItem*>()); //insert empty items into map
        }
    }
    qDebug()<<"Stocks: "<<stocks;

    qDebug()<<"Init model";
    initModel(QString(VALUE_NAMES).split(","));  //init model for view

    /*connect*/
    if(flag!=LOAD_NO_STOCKS)
    {
        //TODO: put it in a own function
        qDebug()<<"verbinde";
        QString url="/streamer/1.0?s="+stockSymbols.join(",")+"&k="+VALUE_SYMBOLS+"&j="+VALUE_SYMBOLS+"&r=0&callback=parent.yfs_u1f&mktmcb=parent.yfs_mktmcb&gencallback=parent.yfs_gencb&region=DE&lang=de-DE&localize=0&mu=1";
        ConnectionHandler::instance()->setUrl("streamerapi.finance.yahoo.com",url);
    }
   // model->setRowCount(stocknames.count());                         //set rows (count of stocks)
}

void Stock::getColumnPairsFromDB(QList<QPointF>* p,const QString& s1,const QString& s2,const QString& s3,bool b)
{
    getColumnPairs(p,s1,s2,s3,b);
}

void Stock::setStaticStockNames(const QStringList &stockNames)
{
    staticStockNames=stockNames;
}

QStringList Stock::getStaticStockNames() const
{
    return staticStockNames;
}
